import { ChangeDetectorRef, Component, Input, OnInit, ViewChild } from '@angular/core';
import { _HttpClient } from '@delon/theme';
import { NzTreeNodeOptions } from 'ng-zorro-antd/core/tree';
import { NzTreeNode } from 'ng-zorro-antd/core/tree/nz-tree-base-node';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzDrawerRef } from 'ng-zorro-antd/drawer';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzFormatEmitEvent, NzTreeComponent } from 'ng-zorro-antd/tree';

@Component({
  selector: 'app-sys-assign-permission',
  templateUrl: './permission.component.html'
})
export class SysAssignPermissionComponent implements OnInit {
  i: any;
  @Input() record: NzSafeAny;
  nodes: NzTreeNodeOptions[] = [];
  checked: any;
  hasChecked = false;
  checkedNodes: number[] = [];
  halfCheckedNodes: number[] = [];

  @ViewChild('treeComponent', { static: false }) treeComponent!: NzTreeComponent;
  constructor(public http: _HttpClient, private drawer: NzDrawerRef, private cdr: ChangeDetectorRef, private msgSrv: NzMessageService) {}

  ngOnInit(): void {
    this.loadData();
  }

  loadData(): void {
    if (this.record.ID > 0) {
      this.http.get(`api/role/${this.record.ID}/permissions`).subscribe(res => {
        if (res.err_code == 0) {
          this.i = true;
          this.nodesFormat(res.data);
          this.checkedFormat(res.data);
        }
      });
    }
  }

  nodesFormat(nodes: any): any {
    let tmpNodes: NzTreeNodeOptions[string] = [];
    for (let i = 0; i < nodes.length; i++) {
      let tmpNode = {
        id: nodes[i].ID,
        key: `${nodes[i].uri} - ${nodes[i].method}`,
        title: `${nodes[i].name}（${nodes[i].uri} - ${nodes[i].method}）`,
        disabled: nodes[i].disabled,
        isLeaf: true
      };
      if (nodes[i].group && !tmpNodes[nodes[i].group]) {
        tmpNodes[nodes[i].group] = [];
      }
      tmpNodes[nodes[i].group].push(tmpNode);
    }
    for (let i in tmpNodes) {
      this.nodes.push({
        id: 0,
        key: i,
        title: i,
        children: tmpNodes[i]
      });
    }
    return this.nodes;
  }

  checkedFormat(checked: any): void {
    if (checked) {
      this.hasChecked = true;
      this.cdr.detectChanges();
      this.checked = [];
      for (let i = 0; i < checked.length; i++) {
        if (checked[i]['checked']) {
          this.checked.push(`${checked[i].uri} - ${checked[i].method}`);
        }
      }
    }
  }

  save(): void {
    const treeNodes = this.treeComponent.getTreeNodes();
    this.getCheckedNodeIds(treeNodes);
    this.http
      .post(`api/role/${this.record.ID}/permissions`, { checked: this.checkedNodes, halfChecked: this.halfCheckedNodes })
      .subscribe(res => {
        if (res.err_code != 0) {
          this.msgSrv.error(res.msg);
          return;
        }
        this.msgSrv.success(res.msg);
        this.drawer.close(true);
      });
  }

  getCheckedNodeIds(nodes: NzTreeNode[]): void {
    // console.log(nodes);
    for (let i = 0; i < nodes.length; i++) {
      let node = nodes[i];
      if (node.isChecked) {
        if (!node.isDisabled && node.isLeaf) {
          if (node.origin.id > 0) {
            this.checkedNodes.push(node.origin.id);
          }
        } else {
          let hasDisabled = false;
          node.children.forEach((value: NzTreeNode) => {
            if (value.isDisabled) {
              hasDisabled = true;
              return;
            }
          });
          if (hasDisabled) {
            if (node.origin.id > 0) {
              this.halfCheckedNodes.push(node.origin.id);
            }
          } else {
            if (node.origin.id > 0) {
              this.checkedNodes.push(node.origin.id);
            }
          }
        }
      } else if (node.isHalfChecked) {
        if (node.origin.id > 0) {
          this.halfCheckedNodes.push(node.origin.id);
        }
      }
      if (node.children.length) {
        this.getCheckedNodeIds(node.children);
      }
    }
  }

  close(): void {
    this.drawer.close();
  }

  checkBoxChangeEvent(event: NzFormatEmitEvent): void {
    this.hasChecked = this.treeComponent.getCheckedNodeList().length > 0;
    this.cdr.detectChanges();
  }
}
